package gwtappcontainer.server.apps.security;

import gwtappcontainer.shared.apis.APIResponse;
import gwtappcontainer.shared.apis.APIResponse.Status;
import gwtappcontainer.shared.apps.security.RoleProp;
import gwtappcontainer.shared.apps.security.UserProp;

import java.util.TreeSet;

import javax.inject.Named;

import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiMethod.HttpMethod;
import com.google.appengine.api.users.User;

@Api(name = "security", 
	scopes = { "https://www.googleapis.com/auth/userinfo.email" }
)
public class SecurityAPI {
		
	@ApiMethod(httpMethod  = HttpMethod.PUT, path="addprivilege")
	public APIResponse addPrivilege(@Named("privilege") String privilege, User user) {		
		try {
			AccessController.ensureLoggedin(user);
						
			PrivilegeRepository.addPrivilege(privilege, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "privilege [" + privilege + "] has been added");			
			return response;			
			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod  = HttpMethod.DELETE, path="deleteprivilege")
	public APIResponse deletePrivilege(@Named("privilege") String privilege, User user) {		
		try {
			AccessController.ensureLoggedin(user);			
			
			PrivilegeRepository.deletePrivilege(privilege, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "privilege [" + privilege + "] has been deleted");			
			return response;			
			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.GET, path="getallprivileges")
	public APIResponse getAllPrivileges() {		
		try {
			TreeSet<String> privileges = PrivilegeRepository.getAllPrivileges();
			
			APIResponse response = new APIResponse(Status.SUCCESS, privileges);			
			return response;			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.PUT, path="addrole")
	public APIResponse addRole(@Named("role") String role, User user) {
		try {
			AccessController.ensureLoggedin(user);
						
			RoleRepository.addRole(role, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "role [" + role + "] has been added");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.DELETE, path="deleteRole")
	public APIResponse deleteRole(@Named("role") String role, User user) {
		try {
			AccessController.ensureLoggedin(user);			
			
			RoleRepository.deleteRole(role, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "role [" + role + "] has been deleted");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.GET, path="getAllRoles")
	public APIResponse getAllRoles() {		
		try {
			TreeSet<RoleProp> roles = RoleRepository.getAllRoles();
			
			APIResponse response = new APIResponse(Status.SUCCESS, roles);			
			return response;			
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.POST, path="assignPrivilegeToRole")
	public APIResponse assignPrivilegeToRole(@Named("role") String role, @Named("privilege") String privilege, 
			User user) {
		try {
			AccessController.ensureLoggedin(user);			
			
			RoleRepository.assignPrivilageToRole(role, privilege,user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "privilege [" + privilege + "] assigned to role [" + role + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.POST, path="unassignPrivilegeToRole")
	public APIResponse unassignPrivilegeToRole(@Named("role") String role, @Named("privilege") String privilege, 
			User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			RoleRepository.unassignPrivilageToRole(role, privilege, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "privilege [" + privilege + "] removed from role [" + role + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.PUT, path="addUser")
	public APIResponse addUser(@Named("email") String email, User user) {
		try {
			AccessController.ensureLoggedin(user);			
			
			UserRepository.addUser(email, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"user [" + email + "] has been added");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.DELETE, path="deleteUser")
	public APIResponse deleteUser(@Named("email") String email, User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			UserRepository.deleteUser(email, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "user [" + email + "] has been added");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.POST, path="assignPrivilegeToUser")
	public APIResponse assignPrivilegeToUser(@Named("email") String email, @Named("privilege") String privilege, 
			User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			UserRepository.assignPrivilegeToUser(email, privilege, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "User [" + email + "] now has privilege [" + privilege + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.POST, path="unassignPrivilegeToUser")
	public APIResponse unassignPrivilegeToUser(@Named("email") String email, @Named("privilege") String privilege, 
			User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			UserRepository.unassignPrivilegeToUser(email, privilege, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "User [" + email + "] now does not have privilege [" + privilege + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.POST, path="assignRoleToUser")
	public APIResponse assignRoleToUser(@Named("email") String email, @Named("role") String role, 
			User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			UserRepository.assignRoleToUser(email, role, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "User [" + email + "] now has role [" + role + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.POST, path="unassignRoleToUser")
	public APIResponse unassignRoleToUser(@Named("email") String email, @Named("role") String role, 
			User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			UserRepository.unassignRoleToUser(email, role, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "User [" + email + "] now does not have role [" + role + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	@ApiMethod(httpMethod = HttpMethod.PUT, path="cloneUser")
	public APIResponse cloneUser(@Named("newEmail") String newEmail, 
			@Named("existingEmail") String existingEmail, User user) {
		try {
			AccessController.ensureLoggedin(user);
			
			UserRepository.cloneUser(newEmail, existingEmail, user.getEmail());
			
			APIResponse response = new APIResponse(Status.SUCCESS, 
					"success", "User [" + newEmail + "] added. [" + newEmail + 
					"] has the same roles and privileges as [" + existingEmail + "]");	
			
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	public APIResponse getUser(@Named("email") String email) { 
			
		try {			
			UserProp prop = UserRepository.getUser(email);
						
			APIResponse response = new APIResponse(Status.SUCCESS, prop); 
					
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
	
	public APIResponse getAllUsers() { 
		
		try {			
			TreeSet<UserProp> props = UserRepository.getAllUsers();
						
			APIResponse response = new APIResponse(Status.SUCCESS, props); 
					
			return response;
		} catch (Exception ex) {
			return new APIResponse(ex);
		}
	}
}
